﻿//  --------------------------------
//  Copyright (c) AW Systems, Inc. All rights reserved.
//  This source code is made available under the terms of the Microsoft Public License (Ms-PL)
//  http://www.codeplex.com/SLAM/license
//  ---------------------------------

using System;
using System.Configuration;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;
using System.Xml.Linq;

namespace Slam.StructureMap
{
	public class XmlTypeProfileSection
	{
		#region Private State

		/// <summary>
		/// Regex pattern to validate Guid strings
		/// </summary>
		private static Regex _guidRegex = new Regex(@"^(\{){0,1}[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}(\}){0,1}$", RegexOptions.Compiled);

		private XDocument _configXml;

		#endregion

		public XmlTypeProfileSection(XDocument configurationXml)
		{
			_configXml = configurationXml;
		}

		/// <summary>
		/// Gets all extra Type Profiles defined in the configuration.
		/// </summary>
		/// <returns></returns>
		public IEnumerable<CustomTypeProfile> GetCustomTypeProfiles()
		{
			IEnumerable<CustomTypeProfile> typeProfiles = new List<CustomTypeProfile>();
			if (_configXml.Root.Element("TypeProfiles") != null)
			{
				typeProfiles =
				from typeProfile in _configXml.Root.Element("TypeProfiles").Elements("add")
				select new CustomTypeProfile
				{
					AssemblyQualifiedTypeName = typeProfile.Attribute("AssemblyQualifiedTypeName").Value,
					Name = typeProfile.Attribute("Name").Value,
				};
			}
			return typeProfiles;
		}

		/// <summary>
		/// Gets the Type Profile name for the given type id or name.
		/// </summary>
		/// <param name="id">Optional unique SharePoint List Guid id as string</param>
		/// <param name="typeName">Name of List or ContentType</param>
		/// <returns></returns>
		public string GetTypeProfileName(string siteCollection, string site, string id, string typeName)
		{
			Guid guidId = Guid.Empty;
			XElement selectedNode = null;

			//Selection precedence follows:
			//If ID is present and a valid, Get type that matches ID
			//If no type matches ID, Get type that has TableName matching the typeName
			//Finally, if nothing yet has been selected get the first node that has Name matching the 
			//typeName

			//Check if ID is present and valid
			if (!String.IsNullOrEmpty(id) && _guidRegex.IsMatch(id))
			{
				guidId = new Guid(id);

				selectedNode = (from typeNode in _configXml.Root.Elements().Where(mapping =>
									mapping.Name == "DataMapping" &&
									(String.IsNullOrEmpty(siteCollection) ?
									(mapping.Attribute("SiteCollection") == null ||
									String.IsNullOrEmpty(mapping.Attribute("SiteCollection").Value)) :
									(mapping.Attribute("SiteCollection") != null &&
									mapping.Attribute("SiteCollection").Value.Equals(siteCollection, StringComparison.CurrentCultureIgnoreCase)))).Elements()
								where typeNode.Attribute("ID") != null &&
										typeNode.Attribute("ID").Value == guidId.ToString()
								select typeNode).DefaultIfEmpty().First();
			}

			if (selectedNode == null)
			{
				//Get node matching TableName
				selectedNode = (from typeNode in _configXml.Root.Elements().Where(mapping =>
									mapping.Name == "DataMapping" &&
									(String.IsNullOrEmpty(siteCollection) ?
									(mapping.Attribute("SiteCollection") == null ||
									String.IsNullOrEmpty(mapping.Attribute("SiteCollection").Value)) :
									(mapping.Attribute("SiteCollection") != null &&
									mapping.Attribute("SiteCollection").Value.Equals(siteCollection, StringComparison.CurrentCultureIgnoreCase)))).Elements()
								where typeNode.Attribute("TableName") != null &&
										typeNode.Attribute("TableName").Value == typeName
								select typeNode).DefaultIfEmpty().First();

				//If nothing has yet been selected
				if (selectedNode == null)
				{
					//Get node matching type
					selectedNode = (from typeNode in _configXml.Root.Elements().Where(mapping =>
										mapping.Name == "DataMapping" &&
										(String.IsNullOrEmpty(siteCollection) ?
										(mapping.Attribute("SiteCollection") == null ||
										String.IsNullOrEmpty(mapping.Attribute("SiteCollection").Value)) :
										(mapping.Attribute("SiteCollection") != null &&
										mapping.Attribute("SiteCollection").Value.Equals(siteCollection, StringComparison.CurrentCultureIgnoreCase)))).Elements()
									where typeNode.Attribute("Name").Value == typeName
									select typeNode).DefaultIfEmpty().First();
				}
			}
			
			string typeProfileName = selectedNode.Name.LocalName == "ContentType" ? "DefaultContentType" : "DefaultList";
			if (selectedNode.Attribute("TypeProfile") != null)
			{
				typeProfileName = selectedNode.Attribute("TypeProfile").Value;
			}

			return typeProfileName;
		}
	}
}
